package com.jinlia.show.modules.base.wxapp.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jinlia.show.common.core.exception.MyRuntimeException;
import com.jinlia.show.modules.base.wxapp.entity.AccessToken;
import com.jinlia.show.modules.base.wxapp.entity.AppConfig;
import com.jinlia.show.modules.base.wxapp.mapper.AccessTokenMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
@Service
public class AccessTokenMapperService extends ServiceImpl<AccessTokenMapper, AccessToken> {
    private final ReentrantLock lock = new ReentrantLock(); // 细粒度锁
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private AppConfigMapperService appConfigMapperService;

    public AccessToken getAccessToken(String appId) {
        try {
            lock.lock(); // 使用细粒度锁
            AccessToken aAccessToken = this.lambdaQuery().gt(AccessToken::getExpiresTime, new Date())
                    .eq(AccessToken::getAppid, appId).orderByDesc(AccessToken::getCreateTime).last("limit 1").one();
            if (Objects.nonNull(aAccessToken)) {
                log.debug("使用缓存token:{}", JSONObject.toJSON(aAccessToken));
                return aAccessToken;
            }
            AppConfig oneAppConfig = appConfigMapperService.lambdaQuery().eq(AppConfig::getAppId, appId).one();
            ResponseEntity<String> accessTokenResponse = restTemplate.getForEntity("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={1}&secret={2}",
                    String.class, appId, oneAppConfig.getAppSecret());
            if (HttpStatus.OK.equals(accessTokenResponse.getStatusCode())) {
                log.debug("微信调用成功 = {}", accessTokenResponse.getBody());
                JSONObject accessTokenResponseJson = JSONObject.parseObject(accessTokenResponse.getBody());
                if (Objects.isNull(accessTokenResponseJson.getString("access_token"))) {
                    throw new MyRuntimeException("微信获取accessToken失败");
                }
                AccessToken accessToken = accessTokenResponseJson.toJavaObject(AccessToken.class);
                accessToken.setExpiresTime(LocalDateTime.now().plusSeconds(7000l));
                accessToken.setAppid(appId);
                accessToken.setCreateTime(LocalDateTime.now());
                this.save(accessToken);
                return accessToken;
            }
            throw new MyRuntimeException("调用微信登录aip失败");
        } finally {
            lock.unlock(); // 确保锁释放
        }
    }
}
